<?php

namespace pay\src;

use app\Request;
use think\App;
use think\facade\Config;
use WeChatPay\Formatter;
use WeChatPay\Builder;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;

use think\Response;
use think\Collection;
use Symfony\Component\HttpFoundation\RedirectResponse;


/**
 * @method Response         app(array $config)          APP 支付
 * @method Collection       groupRedpack(array $config) 分裂红包
 * @method Collection       miniapp(array $config)      小程序支付
 * @method Collection       mp(array $config)           公众号支付
 * @method Collection       pos(array $config)          刷卡支付
 * @method Collection       redpack(array $config)      普通红包
 * @method Collection       scan(array $config)         扫码支付
 * @method Collection       transfer(array $config)     企业付款
 * @method RedirectResponse web(array $config)          Web 扫码支付
 * @method RedirectResponse wap(array $config)          H5 支付
 */
class Aliyun
{
    private $appid='';  //微信公众号ID,唯一标识
    private $secret='';  //微信公众号的appsecret
    private $mchid=''; // 商户号
    private $serialNo='';  // 「商户API证书」的「证书序列号」
    private $cert_client='apiclient_key.pem';  //商户API私钥
    private $cert_key='wechatpay_cert.pem'; //微信支付平台证书



    public function __construct()
    {
        $config = Config::get('pay.wechat');

        if (empty($config['cert_client']) || empty($config['cert_key'])) {
            $this->status = false;
        } else {
            $this->status = true;
            $this->appid = $config['app_id'];
            $this->secret = $config['app_secret'];
            $this->mchid = $config['mch_id'];
            $this->serialNo = $config['key'];
            $this->cert_client = $config['cert_client'];
            $this->cert_key = $config['cert_key'];
        }

    }


    public function __call($method, $params)
    {

        return self::pay($method, ...$params);
    }

    public function pay($gateway, $params = [])
    {

        $instance=$this->APIv3();
        $data = array_merge($params,[
            'appid'=>$this->appid, //公众号的服务号APPID
            'mchid'=>$this->mchid, //商户号
        ]);

        try {
            $resp = $instance->chain('v3/pay/transactions/jsapi')->post(['json' => $data]); //jsapi下单
            $prepay_id=json_decode($resp->getBody(),true)['prepay_id'];
            if(isset($prepay_id)){
                $data['code'] = 200;
                $data['msg'] = '下单成功';
            }else{
                $data['code'] = $resp->getStatusCode();
                $data['msg'] = $resp->getBody();
            }

        } catch (\Exception $e) {
            // 进行错误处理
//            echo $e->getMessage(), PHP_EOL;
//            if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
//                $r = $e->getResponse();
//                echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
//                echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
//            }
//            echo $e->getTraceAsString(), PHP_EOL;
            $data['code'] = 500;
            $data['msg'] = $e->getMessage();
        }
        return $data;

    }

    //异步接收微信支付结果通知，自行编写数据处理
    public function notify(){
    }
    //获取支付参数
    public function payConfig(){
        $config=$this->sign('prepay_id值');
        return json($config);
    }
    //微信支付订单号查询
    public function cxTransactionId(){
        $id='420000***93';
        $resp = $this->APIv3()
            ->chain('v3/pay/transactions/id/'.$id)
            ->get(['query' => ['mchid' => $this->mchid]]);
        echo $resp->getBody();
    }
    //商户订单号查询
    public function cxOutTradeNo(){
        $out_trade_no='20221004***02';
        $resp = $this->APIv3()
            ->chain('v3/pay/transactions/out-trade-no/'.$out_trade_no)
            ->get(['query' => ['mchid' => $this->mchid]]);
        echo $resp->getBody();
    }
    //关闭订单
    public function closeOutTradeNo(){
        $out_trade_no='20221004***02';
        $resp = $this->APIv3()
            ->chain('v3/pay/transactions/out-trade-no/'.$out_trade_no.'/close')
            ->post(['json' => ['mchid' => $this->mchid]]);
        echo $resp->getBody(); //正常无返回数据
    }
//=============================================================================
    //构造 APIv3 客户端实例
    private function APIv3(){
        $merchantId = $this->mchid; // 商户号
        // 从本地文件中加载「商户API私钥」，「商户API私钥」会用来生成请求的签名
        $merchantPrivateKeyFilePath = $this->certPath().$this->cert_key;
        $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
        // 「商户API证书」的「证书序列号」
        $merchantCertificateSerial = $this->serialNo;
        // 从本地文件中加载「微信支付平台证书」，用来验证微信支付应答的签名
        $platformCertificateFilePath = $this->certPath().$this->cert_client;
        $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
        // 从「微信支付平台证书」中获取「证书序列号」
        $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);

        // 构造一个 APIv3 客户端实例
        $instance = Builder::factory([
            'mchid'      => $merchantId,
            'serial'     => $merchantCertificateSerial,
            'privateKey' => $merchantPrivateKeyInstance,
            'certs'      => [$platformCertificateSerial => $platformPublicKeyInstance],
        ]);

        return $instance;
    }
    //签名
    private function sign($prepay_id)
    {
        $merchantPrivateKeyFilePath = $this->certPath().$this->keyCert;
        $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath);
        $params = [
            'appId'     => $this->appid,
            'timeStamp' => (string)Formatter::timestamp(),
            'nonceStr'  => Formatter::nonce(),
            'package'   => 'prepay_id='.$prepay_id,
        ];
        $params += ['paySign' => Rsa::sign(
            Formatter::joinedByLineFeed(...array_values($params)),
            $merchantPrivateKeyInstance
        ), 'signType' => 'RSA'];
        return $params;
    }

    private function certPath(){
        return  "file://".root_path();
    }
}